<p>Enabling public network access to cloud resources can affect an organization’s ability to protect its data or internal operations from data theft
or disruption.</p>
<p>Depending on the component, inbound access from the Internet can be enabled via:</p>
<ul>
  <li> a boolean value that explicitly allows access to the public network. </li>
  <li> the assignment of a public IP address. </li>
  <li> database firewall rules that allow public IP ranges. </li>
</ul>
<p>Deciding to allow public access may happen for various reasons such as for quick maintenance, time saving, or by accident.</p>
<p>This decision increases the likelihood of attacks on the organization, such as:</p>
<ul>
  <li> data breaches. </li>
  <li> intrusions into the infrastructure to permanently steal from it. </li>
  <li> and various malicious traffic, such as DDoS attacks. </li>
</ul>
<h2>Ask Yourself Whether</h2>
<p>This cloud resource:</p>
<ul>
  <li> should be publicly accessible to any Internet user. </li>
  <li> requires inbound traffic from the Internet to function properly. </li>
</ul>
<p>There is a risk if you answered no to any of those questions.</p>
<h2>Recommended Secure Coding Practices</h2>
<p>Avoid publishing cloud services on the Internet unless they are intended to be publicly accessible, such as customer portals or e-commerce
sites.</p>
<p>Use private networks (and associated private IP addresses) and VPC peering or other secure communication tunnels to communicate with other cloud
components.</p>
<p>The goal is to prevent the component from intercepting traffic coming in via the public IP address. If the cloud resource does not support the
absence of a public IP address, assign a public IP address to it, but do not create listeners for the public IP address.</p>
<h2>Sensitive Code Example</h2>
<p>For <a href="https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ec2.Instance.html">aws-cdk-lib.aws_ec2.Instance</a> and similar
constructs:</p>
<pre>
import {aws_ec2 as ec2} from 'aws-cdk-lib'

new ec2.Instance(this, "example", {
    instanceType: nanoT2,
    machineImage: ec2.MachineImage.latestAmazonLinux(),
    vpc: vpc,
    vpcSubnets: {subnetType: ec2.SubnetType.PUBLIC} // Sensitive
})
</pre>
<p>For <a href="https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ec2.CfnInstance.html">aws-cdk-lib.aws_ec2.CfnInstance</a>:</p>
<pre>
import {aws_ec2 as ec2} from 'aws-cdk-lib'

new ec2.CfnInstance(this, "example", {
    instanceType: "t2.micro",
    imageId: "ami-0ea0f26a6d50850c5",
    networkInterfaces: [
        {
            deviceIndex: "0",
            associatePublicIpAddress: true, // Sensitive
            deleteOnTermination: true,
            subnetId: vpc.selectSubnets({subnetType: ec2.SubnetType.PUBLIC}).subnetIds[0]
        }
    ]
})
</pre>
<p>For <a
href="https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_dms.CfnReplicationInstance.html">aws-cdk-lib.aws_dms.CfnReplicationInstance</a>:</p>
<pre>
import {aws_ec2 as ec2} from 'aws-cdk-lib'

new dms.CfnReplicationInstance(
    this, "example", {
    replicationInstanceClass: "dms.t2.micro",
    allocatedStorage: 5,
    publiclyAccessible: true, // Sensitive
    replicationSubnetGroupIdentifier: subnetGroup.replicationSubnetGroupIdentifier,
    vpcSecurityGroupIds: [vpc.vpcDefaultSecurityGroup]
})
</pre>
<p>For <a href="https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_rds.CfnDBInstance.html">aws-cdk-lib.aws_rds.CfnDBInstance</a>:</p>
<pre>
import {aws_ec2 as ec2} from 'aws-cdk-lib'

const rdsSubnetGroupPublic = new rds.CfnDBSubnetGroup(this, "publicSubnet", {
    dbSubnetGroupDescription: "Subnets",
    dbSubnetGroupName: "publicSn",
    subnetIds: vpc.selectSubnets({
        subnetType: ec2.SubnetType.PUBLIC
    }).subnetIds
})

new rds.CfnDBInstance(this, "example", {
    engine: "postgres",
    masterUsername: "foobar",
    masterUserPassword: "12345678",
    dbInstanceClass: "db.r5.large",
    allocatedStorage: "200",
    iops: 1000,
    dbSubnetGroupName: rdsSubnetGroupPublic.ref,
    publiclyAccessible: true, // Sensitive
    vpcSecurityGroups: [sg.securityGroupId]
})
</pre>
<h2>Compliant Solution</h2>
<p>For <a href="https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ec2.Instance.html">aws-cdk-lib.aws_ec2.Instance</a> and similar
constructs:</p>
<pre>
import {aws_ec2 as ec2} from 'aws-cdk-lib'

new ec2.Instance(
    this,
    "example", {
    instanceType: nanoT2,
    machineImage: ec2.MachineImage.latestAmazonLinux(),
    vpc: vpc,
    vpcSubnets: {subnetType: ec2.SubnetType.PRIVATE_WITH_EGRESS}
})
</pre>
<p>For <a href="https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ec2.CfnInstance.html">aws-cdk-lib.aws_ec2.CfnInstance</a>:</p>
<pre>
import {aws_ec2 as ec2} from 'aws-cdk-lib'

new ec2.CfnInstance(this, "example", {
    instanceType: "t2.micro",
    imageId: "ami-0ea0f26a6d50850c5",
    networkInterfaces: [
        {
            deviceIndex: "0",
            associatePublicIpAddress: false,
            deleteOnTermination: true,
            subnetId: vpc.selectSubnets({subnetType: ec2.SubnetType.PRIVATE_WITH_EGRESS}).subnetIds[0]
        }
    ]
})
</pre>
<p>For <a
href="https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_dms.CfnReplicationInstance.html">aws-cdk-lib.aws_dms.CfnReplicationInstance</a>:</p>
<pre>
import {aws_ec2 as ec2} from 'aws-cdk-lib'

new dms.CfnReplicationInstance(
    this, "example", {
    replicationInstanceClass: "dms.t2.micro",
    allocatedStorage: 5,
    publiclyAccessible: false,
    replicationSubnetGroupIdentifier: subnetGroup.replicationSubnetGroupIdentifier,
    vpcSecurityGroupIds: [vpc.vpcDefaultSecurityGroup]
})
</pre>
<p>For <a href="https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_rds.CfnDBInstance.html">aws-cdk-lib.aws_rds.CfnDBInstance</a>:</p>
<pre>
import {aws_ec2 as ec2} from 'aws-cdk-lib'

const rdsSubnetGroupPrivate = new rds.CfnDBSubnetGroup(this, "example",{
    dbSubnetGroupDescription: "Subnets",
    dbSubnetGroupName: "privateSn",
    subnetIds: vpc.selectSubnets({
        subnetType: ec2.SubnetType.PRIVATE_WITH_EGRESS
    }).subnetIds
})

new rds.CfnDBInstance(this, "example", {
    engine: "postgres",
    masterUsername: "foobar",
    masterUserPassword: "12345678",
    dbInstanceClass: "db.r5.large",
    allocatedStorage: "200",
    iops: 1000,
    dbSubnetGroupName: rdsSubnetGroupPrivate.ref,
    publiclyAccessible: false,
    vpcSecurityGroups: [sg.securityGroupId]
})
</pre>
<h2>See</h2>
<ul>
  <li> <a href="https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/using-instance-addressing.html">AWS Documentation</a> - Amazon EC2 instance IP
  addressing </li>
  <li> <a href="https://docs.aws.amazon.com/dms/latest/userguide/CHAP_ReplicationInstance.PublicPrivate.html">AWS Documentation</a> - Public and
  private replication instances </li>
  <li> <a href="https://docs.aws.amazon.com/vpc/latest/peering/what-is-vpc-peering.html">AWS Documentation</a> - VPC Peering </li>
  <li> CWE - <a href="https://cwe.mitre.org/data/definitions/284">CWE-284 - Improper Access Control</a> </li>
  <li> CWE - <a href="https://cwe.mitre.org/data/definitions/668">CWE-668 - Exposure of Resource to Wrong Sphere</a> </li>
  <li> STIG Viewer - <a href="https://stigviewer.com/stigs/application_security_and_development/2024-12-06/finding/V-222620">Application Security and
  Development: V-222620</a> - Application web servers must be on a separate network segment from the application and database servers. </li>
</ul>
